from models import GameRecord, User, Game, GameWordlist, UserScores, WordLearningRecord, Wordlist, db
from llm.elevenlabs_tts import text_to_speech_file
from sqlalchemy.exc import SQLAlchemyError
import os
import re
from flask import Flask, render_template, request, redirect, url_for, flash, session, jsonify, Response
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
from llm import doubao
from llm.word_generator import word_info_generator
from collections import defaultdict
from datetime import datetime
from sqlalchemy import func
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
import random
from decimal import Decimal
from user_agents import parse
from functools import wraps
from routes.bunnywrite import bp as bunnywrite_bp
import json
import time
from queue import Queue
import threading

app = Flask(__name__)
app.secret_key = 'your_secret_key'  # 设置 session 的密钥

# Add database configuration with defaults
db_user = os.getenv('DB_USER', 'root')
db_password = os.getenv('DB_PASSWORD', '')
db_host = os.getenv('DB_HOST', 'localhost')
db_name = os.getenv('DB_NAME', 'bunnyspell')  # Replace 'wordgame' with your actual database name

# Build database URI with the configured values
app.config['SQLALCHEMY_DATABASE_URI'] = f"mysql+pymysql://{db_user}:{db_password}@{db_host}/{db_name}"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False


# Initialize SQLAlchemy with the app
db.init_app(app)

# Initialize login manager after db
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'

# Add this near the top of your file, after the imports
GAME_SPELL_SPEED = int(os.getenv('GAME_SPELL_SPEED', 8))  # Default to 8 if not set
# Audio file directory
AUDIO_DIR = os.path.join(os.path.dirname(__file__), 'static', 'audio')
app.config['UPLOAD_FOLDER'] = 'uploads'
ALLOWED_EXTENSIONS = {'txt'}

# 创建一个全局的进度队列字典，用于存储每个用户的进度
progress_queues = {}
progress_locks = {}


@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))


# 检查上传的文件格式否允许


def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


def is_mobile():
    user_agent_string = request.headers.get('User-Agent')
    user_agent = parse(user_agent_string)
    return user_agent.is_mobile


def mobile_check(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if is_mobile() and request.path != '/mobile_warning':
            return redirect(url_for('mobile_warning'))
        return f(*args, **kwargs)
    return decorated_function


@app.route('/mobile_warning')
def mobile_warning():
    return render_template('mobile_warning.html')


@app.route('/')
@mobile_check
def home():
    current_year = datetime.now().year
    return render_template('index.html', current_year=current_year)

# 游戏创建视图，仅允许家长访问


@app.route('/game_creator', methods=['GET', 'POST'])
@login_required
@mobile_check
def game_creator():
    if request.method == 'POST':
        if 'words' not in request.form:
            return jsonify({
                'success': False,
                'message': '请提供单词列表！'
            })

        words_text = request.form['words']
        description = request.form.get('description', '').strip()

        # 获取当前用户今天创建的游戏数量
        today = datetime.now().date()
        today_games_count = Game.query.filter(
            Game.parent_id == current_user.user_id,
            func.date(Game.created_at) == today
        ).count()

        # 生成游戏标题：用户名-日期-序号
        game_title = f"{current_user.username}-{today.strftime('%Y%m%d')}-{today_games_count + 1}"

        # 解析文本内容，按行分割
        words = []
        for line in words_text.strip().split('\n'):
            word = line.strip().lower()
            if word:
                word_entry = Wordlist.query.filter_by(english=word).first()
                if not word_entry:
                    # 如果单词不存在，调用大模型补充信息
                    word_info = get_word_info_from_model(word)
                    if word_info:
                        chinese, phonetic, example, audio_path = word_info
                        word_entry = Wordlist(
                            english=word,
                            chinese=chinese,
                            phonetic=phonetic,
                            example=example,
                            audio=audio_path)
                        db.session.add(word_entry)
                        db.session.commit()
                        words.append(word_entry.word_id)
                else:
                    words.append(word_entry.word_id)

        # 创建新的游戏记录
        new_game = Game(
            parent_id=current_user.user_id,
            title=game_title,
            description=description,
            category='official',
            mode='spell'
        )
        db.session.add(new_game)
        db.session.commit()

        # 将单词列表添加到 game_wordlist 中
        for idx, word_id in enumerate(words):
            game_word = GameWordlist(
                game_id=new_game.game_id,
                word_id=word_id,
                sequence=idx + 1)
            db.session.add(game_word)

        db.session.commit()

        # 在所有处理完成后发送完成信号
        send_completion_signal(current_user.user_id)

        return jsonify({
            'success': True,
            'message': f'游戏 "{game_title}" 创建成功！',
            'game_id': new_game.game_id
        })

    # 获取当前用户创建的游戏
    games = Game.query.filter_by(parent_id=current_user.user_id).all()
    return render_template(
        'game_creator.html',
        games=games)

# 获取大模型补充的单词信息（模拟）


def get_word_info_from_model(word):
    try:
        update_progress(word, 'started')
        generator = word_info_generator([word])
        word_info = next(generator)
        filename = f"{word.lower().replace(' ', '_')}.mp3"
        file_path = os.path.join(AUDIO_DIR, filename)
        audio_path = os.path.join('audio', filename)

        if not os.path.exists(file_path):
            if word_info is not None:
                update_progress(word, 'generating_audio')
                text_to_speech_file(word, file_path)

        if word_info is None:
            update_progress(word, 'failed')
            return None

        update_progress(word, 'completed')
        return word_info['chinese'], word_info['phonetic'], word_info['example'], audio_path
    except Exception as e:
        print(f"Error processing word {word}: {e}")
        update_progress(word, 'failed')
        return None


@app.route('/login', methods=['GET', 'POST'])
@mobile_check
def login():
    if current_user.is_authenticated:
        return redirect(url_for('profile'))

    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        user = User.query.filter_by(username=username).first()
        if user and check_password_hash(user.password_hash, password):
            login_user(user)
            flash(f'Welcome back, {username}!', 'success')
            return redirect(url_for('profile'))
        else:
            flash('Invalid username or password. Please try again!', 'danger')
    return render_template('login.html')

# 注册路由


@app.route('/register', methods=['GET', 'POST'])
@mobile_check
def register():
    if current_user.is_authenticated:
        return redirect(url_for('profile'))

    if request.method == 'POST':
        username = request.form['username']
        email = request.form['email']
        password = request.form['password']
        role = request.form['role']

        # 检查用户名和邮箱是否已存在
        user = User.query.filter(
            (User.username == username) | (
                User.email == email)).first()
        if user:
            flash('用户名或邮箱存在，请使用其他信！', 'danger')
            return redirect(url_for('register'))

        # 加密密码并创建用户
        hashed_password = generate_password_hash(password)
        new_user = User(username=username, email=email, password_hash=hashed_password, role=role)

        # 将用户添加到数据库中
        db.session.add(new_user)
        db.session.commit()

        flash('Registration successful! Please login.', 'success')
        return redirect(url_for('login'))

    return render_template('register.html')


@app.route('/game_spell')
@login_required
@mobile_check
def game_spell():
    # 从 URL 参数中获取 game_id
    game_id = request.args.get('game_id')
    if not game_id:
        # 随机获取一个有效的game id
        random_game = Game.query.order_by(func.random()).first()
        if random_game:
            game_id = random_game.game_id
        else:
            game_id = 1  # 如果没有任何游戏,用默认值1

    # 获取游信息
    game = Game.query.get(game_id)
    if not game:
        flash('游戏不存在！', 'danger')
        return redirect(url_for('home'))

    # 获取该游戏的单词列表及其相关信息
    game_words = (
        db.session.query(
            Wordlist.english,
            Wordlist.chinese,
            Wordlist.phonetic,
            Wordlist.example,
            Wordlist.audio)
        .join(GameWordlist, Wordlist.word_id == GameWordlist.word_id)
        .filter(GameWordlist.game_id == game_id)
        .order_by(GameWordlist.sequence)
        .all())

    # 处理example，将单词替换为[]（不区分大小写）
    processed_game_words = []
    for word in game_words:
        english, chinese, phonetic, example, audio = word
        if example:
            example = re.sub(re.escape(english), '[ ]', example, flags=re.IGNORECASE)
        processed_game_words.append((english, chinese, phonetic, example, audio))

    # 将查询结果转换为字典格式传递给前端
    word_dict = {
        word[0]: {
            "meaning": word[1],
            "pronunciation": word[2],
            "example": word[3],
            "audio": url_for('static', filename=word[4]) if word[4] else None
        } for word in processed_game_words
    }

    # Print audio URLs for debugging
    for word, info in word_dict.items():
        print(f"Audio URL for '{word}': {info['audio']}")

    # Add this line before rendering the template
    game_spell_speed = GAME_SPELL_SPEED

    # Modify the render_template call to include game_spell_speed
    return render_template(
        'game_spell.html',
        word_dict=word_dict,
        game_id=game_id,
        game_title=game.title,
        game_spell_speed=game_spell_speed)


@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('login'))


@app.route('/submit_game_result', methods=['POST'])
@login_required
def submit_game_result():
    data = request.json
    game_id = data.get('game_id')
    game_mode = data.get('game_mode')
    score = data.get('score')
    completion_rate = Decimal(str(data.get('completion_rate', '0')))  # Convert to Decimal
    word_results = data.get('word_results', [])

    try:
        # Update game record
        existing_record = GameRecord.query.filter_by(
            game_id=game_id, user_id=current_user.user_id, game_mode=game_mode).first()
        if existing_record:
            existing_record.score = score
            existing_record.completion_rate = completion_rate
            existing_record.status = 'completed'
            existing_record.completed_at = db.func.now()
        else:
            new_record = GameRecord(
                game_id=game_id,
                user_id=current_user.user_id,
                game_mode=game_mode,
                score=score,
                completion_rate=completion_rate,
                status='completed',
                completed_at=db.func.now()
            )
            db.session.add(new_record)

        # Update user_scores
        user_score = UserScores.query.filter_by(user_id=current_user.user_id).first()
        if not user_score:
            user_score = UserScores(user_id=current_user.user_id)
            db.session.add(user_score)
            db.session.flush()

        # Update score totals
        user_score.score += score
        user_score.games += 1

        # Update game type counts
        if game_mode == 'spell':
            user_score.spell_count += 1
        elif game_mode == 'translate':
            user_score.trans_count += 1
        else:
            user_score.other_count += 1

        # Calculate new average completion rate
        if user_score.games > 0:
            user_score.avg_rate = (
                (Decimal(str(user_score.avg_rate)) * (user_score.games - 1) + completion_rate)
                / user_score.games
            )

        # Update word learning records
        for result in word_results:
            word = result['word']
            is_correct = result['correct']

            word_entry = Wordlist.query.filter_by(english=word).first()
            if not word_entry:
                continue

            learning_record = WordLearningRecord.query.filter_by(
                user_id=current_user.user_id,
                word_id=word_entry.word_id
            ).first()

            if learning_record:
                if game_mode == 'spell':
                    if is_correct:
                        learning_record.spell_correct_count += 1
                    else:
                        learning_record.spell_wrong_count += 1
                elif game_mode == 'translate':
                    if is_correct:
                        learning_record.translate_correct_count += 1
                    else:
                        learning_record.translate_wrong_count += 1
            else:
                new_record = WordLearningRecord(
                    user_id=current_user.user_id,
                    word_id=word_entry.word_id,
                    spell_correct_count=1 if is_correct and game_mode == 'spell' else 0,
                    spell_wrong_count=0 if is_correct or game_mode == 'translate' else 1,
                    translate_correct_count=1 if is_correct and game_mode == 'translate' else 0,
                    translate_wrong_count=0 if is_correct or game_mode == 'spell' else 1
                )
                db.session.add(new_record)

        db.session.commit()
        return jsonify({'status': 'success', 'message': 'Game results submitted successfully'})

    except SQLAlchemyError as e:
        db.session.rollback()
        app.logger.error(f"Database error occurred: {str(e)}")
        return jsonify(
            {'status': 'error', 'message': 'An error occurred while saving the results'}), 500


@app.route('/profile')
@login_required
@mobile_check
def profile():
    try:
        # Get user scores from user_scores table
        user_score = UserScores.query.filter_by(user_id=current_user.user_id).first()

        # Get game records with pagination
        page = request.args.get('page', 1, type=int)
        per_page = 100

        records = db.session.query(
            GameRecord,
            Game.title.label('game_title'),
            Game.description.label('game_description'),
            User.username.label('creator_username')
        ).join(
            Game, GameRecord.game_id == Game.game_id
        ).join(
            User, Game.parent_id == User.user_id
        ).filter(
            GameRecord.user_id == current_user.user_id
        ).order_by(
            GameRecord.completed_at.desc()
        ).paginate(page=page, per_page=per_page, error_out=False)

        # Get statistics from user_scores
        total_games = user_score.games if user_score else 0
        total_score = user_score.score if user_score else 0
        average_completion = user_score.avg_rate if user_score else 0

        # Group records by date
        grouped_records = defaultdict(list)
        for record in records.items:
            date = record.GameRecord.completed_at.date()
            grouped_records[date].append(record)

        return render_template('profile.html',
                               username=current_user.username,
                               total_games=total_games,
                               total_score=total_score,
                               average_completion=average_completion,
                               grouped_records=grouped_records,
                               pagination=records)

    except SQLAlchemyError as e:
        # Log the error
        app.logger.error(f"Database error occurred: {str(e)}")
        flash("An error occurred while fetching your game records. Please try again later.", "error")
        return redirect(url_for('home'))


@app.route('/game_list')
@login_required
@mobile_check
def game_list():
    # Query games that are either:
    # 1. official games (accessible to all)
    # 2. created by the current user (including temp games)
    games = Game.query.filter(
        db.or_(
            Game.category == 'official',
            Game.parent_id == current_user.user_id
        )
    ).order_by(Game.created_at.desc()).all()

    return render_template('game_list.html', games=games)


@app.route('/game_details/<int:game_id>')
@login_required
@mobile_check
def game_details(game_id):
    game = Game.query.get_or_404(game_id)
    words = db.session.query(Wordlist).join(GameWordlist).filter(
        GameWordlist.game_id == game_id).all()

    game_data = {
        'title': game.title,
        'description': game.description,
        'created_at': game.created_at.strftime('%Y-%m-%d %H:%M:%S'),
        'mode': game.mode,
        'words': [{'english': word.english, 'chinese': word.chinese} for word in words]
    }

    return jsonify(game_data)


@app.route('/game_translate')
@login_required
@mobile_check
def game_translate():
    # Get game_id from URL parameters
    game_id = request.args.get('game_id')
    if not game_id:
        # Get a random game from the database
        random_game = Game.query.order_by(db.func.random()).first()
        if not random_game:
            flash('No games available', 'error')
            return redirect(url_for('game_translate'))
        game_id = random_game.game_id

    game_title = Game.query.get(game_id).title
    # Get game info and its words
    words = (
        db.session.query(
            Wordlist.english,
            Wordlist.chinese,
            Wordlist.phonetic,
            Wordlist.example,
            Wordlist.audio
        )
        .join(GameWordlist, Wordlist.word_id == GameWordlist.word_id)
        .filter(GameWordlist.game_id == game_id)
        .order_by(GameWordlist.sequence)  # Maintain the sequence defined in game_wordlist
        .all()
    )

    if not words:
        flash('No words found for this game', 'error')
        return redirect(url_for('game_translate'))

    # Convert query results to dictionary list
    word_list = []
    for word in words:
        word_dict = {
            'english': word.english,
            'chinese': word.chinese,
            'phonetic': word.phonetic,
            'example': word.example,
            'audio': url_for('static', filename=word.audio) if word.audio else None
        }
        word_list.append(word_dict)

    return render_template(
        'game_translate.html',
        words=word_list,
        game_id=game_id,
        game_title=game_title
    )


@app.route('/check_translation', methods=['POST'])
def check_translation():
    data = request.json
    user_answer = data.get('user_answer', '').strip()
    english_word = data.get('english_word', '').strip()

    # Modified prompt to focus on translation evaluation
    prompt = f"""
    请判断以下英文单词的中文翻译是否正确:
    英文单词: {english_word}
    用户翻译: {user_answer}

    只需要返回 "正确" 或 "错误" 以及简短的解释。如果错误，请给出正确的翻译。
    """

    # Call LLM for evaluation
    response = doubao.call_doubao_api(prompt)

    # Parse response
    is_correct = "正确" in response

    return jsonify({
        'correct': is_correct,
        'message': response
    })


@app.route('/admin', methods=['GET', 'POST'])
@login_required
@mobile_check
def admin():
    # Check if user is vastheaven
    if current_user.username != 'vastheaven':
        flash('You do not have permission to access this page!', 'danger')
        return redirect(url_for('home'))

    if request.method == 'POST':
        username = request.form.get('username')
        new_password = request.form.get('new_password')

        user = User.query.filter_by(username=username).first()
        if user:
            # Update password
            user.password_hash = generate_password_hash(new_password)
            db.session.commit()
            flash(f'Password reset successful for user {username}', 'success')
        else:
            flash(f'User {username} not found', 'danger')

    # Get all users for display
    users = User.query.order_by(User.created_at.desc()).all()
    return render_template('admin.html', users=users)


@app.route('/random_game')
@login_required
@mobile_check
def random_game():
    # 随机选择游戏类型
    game_type = random.choice(['spell', 'translate'])
    return redirect(url_for(f'game_{game_type}'))


@app.route('/words_learned')
@login_required
@mobile_check
def words_learned():
    words_with_records = db.session.query(
        Wordlist,
        WordLearningRecord
    ).outerjoin(
        WordLearningRecord,
        db.and_(
            WordLearningRecord.word_id == Wordlist.word_id,
            WordLearningRecord.user_id == current_user.user_id
        )
    ).order_by(Wordlist.english).all()

    words = []
    for word, record in words_with_records:
        if record is None:
            spell_status = 'not-started'
            translate_status = 'not-started'
        else:
            # Calculate spell status
            spell_total = record.spell_correct_count + record.spell_wrong_count
            spell_mastery = record.spell_correct_count / spell_total if spell_total > 0 else 0

            if spell_total == 0:
                spell_status = 'not-started'
            elif spell_mastery > 0.6:
                spell_status = 'mastered'
            elif spell_mastery > 0.3:
                spell_status = 'learning'
            else:
                spell_status = 'struggling'

            # Calculate translate status
            translate_total = record.translate_correct_count + record.translate_wrong_count
            translate_mastery = record.translate_correct_count / translate_total if translate_total > 0 else 0

            if translate_total == 0:
                translate_status = 'not-started'
            elif translate_mastery > 0.6:
                translate_status = 'mastered'
            elif translate_mastery > 0.3:
                translate_status = 'learning'
            else:
                translate_status = 'struggling'

        words.append({
            'english': word.english,
            'spell_status': spell_status,
            'translate_status': translate_status
        })

    return render_template('words_learned.html', words=words)


@app.route('/user_settings', methods=['GET', 'POST'])
@login_required
@mobile_check
def user_settings():
    if request.method == 'POST':
        current_password = request.form.get('current_password')
        new_password = request.form.get('new_password')
        confirm_password = request.form.get('confirm_password')

        # Verify current password
        if not check_password_hash(current_user.password_hash, current_password):
            flash('Current password is incorrect', 'error')
            return redirect(url_for('user_settings'))

        # Verify new password matches confirmation
        if new_password != confirm_password:
            flash('New passwords do not match', 'error')
            return redirect(url_for('user_settings'))

        # Update password
        try:
            current_user.password_hash = generate_password_hash(new_password)
            db.session.commit()
            flash('Password updated successfully', 'success')
            return redirect(url_for('profile'))
        except SQLAlchemyError as e:
            db.session.rollback()
            flash('An error occurred while updating your password', 'error')
            app.logger.error(f"Database error occurred: {str(e)}")
            return redirect(url_for('user_settings'))

    return render_template('user_settings.html')


@app.route('/create_game_from_words', methods=['POST'])
@login_required
def create_game_from_words():
    try:
        data = request.json
        words = data.get('words', [])

        if not words:
            return jsonify({
                'success': False,
                'message': 'No words selected'
            })

        # Create new game title with timestamp
        timestamp = datetime.now().strftime('%Y%m%d-%H%M%S')
        game_title = f"Temp-{current_user.username}-{timestamp}"
        game_description = f"Created by {current_user.username} on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"

        # Create new game with category='temp'
        new_game = Game(
            parent_id=current_user.user_id,
            title=game_title,
            description=game_description,
            category='temp',  # Added category field
            mode='spell'
        )
        db.session.add(new_game)
        db.session.flush()  # Get the game_id before committing

        # Add words to game_wordlist
        for idx, word_english in enumerate(words):
            word = Wordlist.query.filter_by(english=word_english).first()
            if word:
                game_word = GameWordlist(
                    game_id=new_game.game_id,
                    word_id=word.word_id,
                    sequence=idx + 1
                )
                db.session.add(game_word)

        db.session.commit()

        # Generate game URLs
        spell_url = url_for('game_spell', game_id=new_game.game_id, _external=True)
        translate_url = url_for('game_translate', game_id=new_game.game_id, _external=True)

        return jsonify({
            'success': True,
            'game_id': new_game.game_id,
            'spell_url': spell_url,
            'translate_url': translate_url
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': str(e)
        })


@app.route('/leaderboard')
@mobile_check
def leaderboard():
    page = request.args.get('page', 1, type=int)
    per_page = 50

    # Modified query to include last_played time
    user_stats = db.session.query(
        User.username,
        UserScores.games.label('total_games'),
        UserScores.score.label('total_score'),
        UserScores.avg_rate.label('avg_rate'),
        UserScores.updated_at.label('last_played')
    ).join(
        UserScores,
        User.user_id == UserScores.user_id
    ).order_by(
        UserScores.score.desc()
    ).paginate(page=page, per_page=per_page, error_out=False)

    # Modified dictionary creation to include last_played
    top_users = [
        {
            'username': stats.username,
            'total_games': stats.total_games,
            'total_score': stats.total_score,
            'avg_score': stats.avg_rate,
            'last_played': stats.last_played
        }
        for stats in user_stats.items
    ]

    return render_template('leaderboard.html',
                           top_users=top_users,
                           pagination=user_stats,
                           current_user=current_user)


@app.route('/game_creation_progress')
@login_required
def game_creation_progress():
    user_id = current_user.user_id

    # 为每个用户创建专属的队列
    if user_id not in progress_queues:
        progress_queues[user_id] = Queue()
        progress_locks[user_id] = threading.Lock()

    def generate():
        while True:
            # 检查队列中是否新的进度更新
            try:
                if not progress_queues[user_id].empty():
                    progress = progress_queues[user_id].get_nowait()
                    if progress.get('type') == 'complete':
                        # 清理资源
                        with progress_locks[user_id]:
                            if user_id in progress_queues:
                                del progress_queues[user_id]
                                del progress_locks[user_id]
                        yield f"data: {json.dumps(progress)}\n\n"
                        break
                    yield f"data: {json.dumps(progress)}\n\n"
                else:
                    yield f"data: {json.dumps({'type': 'heartbeat'})}\n\n"
                time.sleep(0.5)
            except Exception as e:
                print(f"Error in generate: {e}")
                break

    return Response(generate(), mimetype='text/event-stream')


def update_progress(word, status):
    """更新进度信息"""
    if not hasattr(update_progress, 'user_id'):
        # 存储当前用户ID
        update_progress.user_id = current_user.user_id

    user_id = update_progress.user_id

    # 确保用户有对应的队列
    if user_id not in progress_queues:
        with threading.Lock():
            if user_id not in progress_queues:
                progress_queues[user_id] = Queue()
                progress_locks[user_id] = threading.Lock()

    # 添加进度信息到队列
    with progress_locks[user_id]:
        progress_queues[user_id].put({
            'type': 'progress',
            'word': word,
            'status': status
        })


# 在游戏创建完成后添加完成信号
def send_completion_signal(user_id):
    """发送完成信号"""
    if user_id in progress_queues and user_id in progress_locks:
        with progress_locks[user_id]:
            progress_queues[user_id].put({
                'type': 'complete',
                'message': 'Game creation completed'
            })


# Register blueprints
app.register_blueprint(bunnywrite_bp)  # Add this line after app initialization


if __name__ == '__main__':
    app.run(
        host='0.0.0.0', port=int(
            os.getenv(
                'SERVER_PORT', 8080)), debug=os.getenv(
            'SERVER_DEBUG', 'False').lower() == 'true')
